#ifndef DATA_PROVIDER_HPP
#define DATA_PROVIDER_HPP

#include <type_traits>
#include <memory>
#include <string>
#include "content/image.hpp"
#include "sdk_config.h"
#include "core/macros.h"
#include "content/view_base.hpp"

// FWD
class data_provider;

enum data_category: u64 {
    signed_integral   = FLAG(0),
    unsigned_integral = FLAG(1),
    floating_point    = FLAG(2),
    boolean           = FLAG(3),

    std_string        = FLAG(10),
    c_string          = FLAG(11),

    callback          = FLAG(20),
    enumerate         = FLAG(21),

    image             = FLAG(30),
    ui                = FLAG(31),

    none              = 0,

    // MASK VALUES
    number            = MASK(0,3),
};

using data_flags = std::underlying_type_t<data_category>;

struct c_string_t {
    char *buff;
    u32   length;
};

struct callback_t {
    void (*action)(void *usr);  // 回调函数，usr是用户数据
    void *user_data;            // 用户数据
};

struct enumerate_t {
    data_provider *count;       // 项个数
    const char *(*text)(void* usr, u32 idx); // 获取项的显示文本，usr是用户数据，idx是第几项，从0开始
    void *user_data;    // 用户数据
};

class bindable_base;

class PI_API data_provider {
public:
    virtual ~data_provider();

    // 获取数据类型
    virtual data_category type() const = 0;

    virtual void attach(bindable_base *ctx);

    // 数据获取, 所有默认实现都是抛出异常
#define TYPE_RO(t,n)         \
    virtual t get_##n()

#define TYPE_RW(t,n)         \
    TYPE_RO(t,n);            \
    virtual void set_##n(t v)

    TYPE_RW(s64,s64);
    TYPE_RW(u64,u64);
    TYPE_RW(f64,f64);
    TYPE_RW(bool,boolean);
    TYPE_RW(std::string,std_string);
    TYPE_RO(c_string_t,cstring);
    TYPE_RO(callback_t,callback);
    TYPE_RO(enumerate_t,enumerate);
    TYPE_RO(ImageContent*,image);
    TYPE_RO(ui_view*,ui);

#undef TYPE_RW
#undef TYPE_RO
};

using data_provider_p = std::shared_ptr<data_provider>;

PI_API
data_provider_p create_data(const std::string &info, data_flags compatible);

#endif // DATA_PROVIDER_HPP
